﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
//using Microsoft.Practices.EnterpriseLibrary.Caching;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using System.Reflection.Emit;

namespace ERP.BusinessEntities.Util
{
    public class DynamicReflect:IReflectUtil
    {
        
        public static Dictionary<String, GetHandler> lstGetHandler = new Dictionary<String, GetHandler>();
        public static Dictionary<String, SetHandler> lstSetHandler = new Dictionary<String, SetHandler>();
        public static Dictionary<String, InstantiateObjectHandler> lstInstanceHandler = new Dictionary<String, InstantiateObjectHandler>();

        public object GetProperty(object obj, string strPropertyName)
        {
            PropertyInfo prop = obj.GetType().GetProperty(strPropertyName);
            return GetProperty(obj, prop);
        }
        public object GetProperty(object obj, System.Reflection.PropertyInfo prop)
        {
            Type type = obj.GetType();
            return GetProperty(obj, type, prop);
        }
        public object GetProperty(object obj, FieldInfo fld)
        {
            Type type = obj.GetType();
            return GetProperty(obj, type, fld);
        }
        public object GetProperty(object obj, Type type, System.Reflection.PropertyInfo prop)
        {
            if (prop == null) return null;
            String strKey = type.Name + "_get" + prop.Name;
            GetHandler getHandler = null;
            lstGetHandler.TryGetValue(strKey, out getHandler);
            if (getHandler != null)
                return getHandler(obj);

            getHandler = DynamicMethodCompiler.CreateGetHandler(type, prop);
            lstGetHandler.Add(strKey, getHandler);
            return getHandler(obj);
        }
        public object GetProperty(object obj, Type type, FieldInfo fld)
        {
            String strKey = type.Name + "_get" + fld.Name;
            GetHandler getHandler = null; 
            lstGetHandler.TryGetValue(strKey, out getHandler);
            if (getHandler != null)
            {
                return getHandler(obj);
            }
            getHandler = DynamicMethodCompiler.CreateGetHandler(type, fld);
            lstGetHandler.Add(strKey, getHandler);
            return getHandler(obj);
        }

        public void SetProperty(object obj, string strPropName, object value)
        {
            Type type = obj.GetType();
            PropertyInfo prop = type.GetProperty(strPropName);
            SetProperty(obj, prop, value);

        }
        public void SetProperty(object obj, System.Reflection.PropertyInfo prop, object value)
        {
            Type type = obj.GetType();
            SetProperty(obj, type, prop, value);
        }
        public void SetProperty(object obj, Type type, PropertyInfo prop, object value)
        {
            String strKey = type.Name + "_set" + prop.Name;
            SetHandler setHandler = null;
            lstSetHandler.TryGetValue(strKey, out setHandler);
            if (setHandler != null)
            {
                setHandler(obj, value);
            }
            else
            {
                setHandler = DynamicMethodCompiler.CreateSetHandler(type, prop);
                lstSetHandler.Add(strKey, setHandler);
                setHandler(obj, value);
            }
            
        }
        public void SetProperty(object obj, Type type, FieldInfo fld, object value)
        {
            String strKey = type.Name + "_set" + fld.Name;
            SetHandler setHandler = null;
            lstSetHandler.TryGetValue(strKey, out setHandler);
            if (setHandler != null)
            {
                setHandler(obj, value);
            }
            else
            {
                setHandler = DynamicMethodCompiler.CreateSetHandler(type, fld);
                lstSetHandler.Add(strKey, setHandler);
                setHandler(obj, value);
            }
        }

        public object CreateInstance(String strType)
        {
            Type type = Type.GetType(strType);
            return CreateInstance(type);
        }
        public object CreateInstance(Type type)
        {
            String strKey = type.Name + "_Instance";
            InstantiateObjectHandler instanceHandler = null;
            lstInstanceHandler.TryGetValue(strKey, out instanceHandler);
            if (instanceHandler != null)
                return instanceHandler();
            instanceHandler = DynamicMethodCompiler.CreateInstantiateObjectHandler(type);
            lstInstanceHandler.Add(strKey, instanceHandler);
            return instanceHandler();
        }

    }
}
